package com.laogao.utils;

import com.laogao.po.SysDictData;
import com.laogao.service.ISysDictDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 第20课：通用实体类字典字段填充工具
 * <b>description</b>： Java进阶、性能优化实战案例100讲，微信公众号:程序员恰恰，源码 & 文档 & 技术支持，请加个人微信号：it3306 <br>
 * <b>time</b>：2025/3/8 21:27 <br>
 * <b>author</b>：ready lao_gao
 */
@Slf4j
@Component
public class AutoFillNameUtils implements ApplicationContextAware {

    private static final String ITEM_ID = "ItemId";
    private static final String ID = "Id";
    private static final String NAME = "Name";

    private static ApplicationContext applicationContext;

    /**
     * @param items 类集合
     */
    public static void setItemNamesForObjectList(List<?> items) {
        for (Object item : items) {
            Class<?> clazz = item.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (field.getName().endsWith(ITEM_ID) && field.getType() == Long.class) {
                    field.setAccessible(true);
                    try {
                        fillNameByItemId(item, clazz, field);
                    } catch (NoSuchFieldException | IllegalAccessException e) {
                        log.error(" >>>> 类:[{}.{}] 缺少对应的名字字段: {}", clazz, field.getName(), field.getName().replace(ID, NAME));
                    }
                }
            }
        }
    }

    /**
     * @param item 类
     */
    public static void setItemNamesForObject(Object item) {
        Class<?> clazz = item.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //获取IdItemId
            if (field.getName().endsWith("ItemId") && field.getType() == Long.class) {
                field.setAccessible(true);
                try {
                    fillNameByItemId(item, clazz, field);
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    log.error(" >>>>> 类:[{}.{}] 缺少对应的名字字段: {}", clazz, field.getName(), field.getName().replace(ID, NAME));
                }
            }
        }
    }

    /**
     * 填充字典名称
     *
     * @param item  类
     * @param clazz 类Class 对象
     * @param field xxxItemId字段对象(Long类型)
     * @throws IllegalAccessException 获取字段值异常
     * @throws NoSuchFieldException   字段不存在异常
     */
    private static void fillNameByItemId(Object item, Class<?> clazz, Field field) throws IllegalAccessException, NoSuchFieldException {
        // 获取字段值
        Long id = (Long) field.get(item);
        if (id != null) {
            // 根据ItemId字段名推导出Name字段名
            String nameField = field.getName().replace(ID, NAME);
            // 获取Name字段对象
            Field nameFieldObj = clazz.getDeclaredField(nameField);
            //访问私有字段，需设置 Field 对象的 setAccessible(true)
            nameFieldObj.setAccessible(true);
            // 根据ID获取名称
            String name = getNameById(id);
            // 将名称设置到Name字段中
            nameFieldObj.set(item, name);
        }
    }

    /**
     * 获取字典Map
     *
     * @return 字典Map
     */
    static Map<Long, String> getMap() {
        Map<Long, String> map = new HashMap<>(3);
        map.put(1L, "A");
        map.put(2L, "B");
        map.put(3L, "C");
        return map;
    }

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        applicationContext = context;
    }

    /**
     * 获取字典Map
     *
     * @return Map<字典id, 字典名称>
     */
    public static Map<Long, String> getDictDataMap() {
        Map<Long, String> dictMap = new HashMap<>();
        try {
            // 1. 获取Service实例
            ISysDictDataService service = applicationContext.getBean(ISysDictDataService.class);
            // 2. 查询字典数据列表
            List<SysDictData> dataList = service.list();
            // 3. 转换为Map（处理空值和重复键）
            if (dataList != null) {
                dictMap = dataList.stream()
                        .filter(data -> data.getDictCode() != null)
                        .collect(Collectors.toMap(
                                // Key: dictCode
                                SysDictData::getDictCode,
                                // Value: dictValue
                                SysDictData::getDictLabel,
                                // 重复键保留第一个
                                (existing, replacement) -> existing
                        ));
            }
        } catch (Exception e) {
            // 生产环境建议使用日志框架：
            log.error("字典数据转换异常", e);
        }
        return dictMap;
    }

    /**
     * 根据字典id获取字典名称
     *
     * @param id 字典id
     * @return 字典名称
     */
    static String getNameById(Long id) {
        return getDictDataMap().get(id);
    }
}